package com.yanqu.road.server.gameplayer.module.activity.goddess;

import com.alibaba.fastjson.JSON;
import com.yanqu.road.dao.impl.activity.goddess.GoddessUserDataDaoImpl;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.args.ValueFourParamArgs;
import com.yanqu.road.entity.activity.args.ValueParamArgs;
import com.yanqu.road.entity.activity.cat.Position;
import com.yanqu.road.entity.activity.goddess.*;
import com.yanqu.road.entity.activity.goddess.config.*;
import com.yanqu.road.entity.activity.goddess.enums.eGoddessItems;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.LogGoddessColorStone;
import com.yanqu.road.entity.log.LogGoddessEnergy;
import com.yanqu.road.entity.log.LogGoddessMakePeople;
import com.yanqu.road.entity.log.LogGoddessMission;
import com.yanqu.road.logic.helper.CalcPowerResult;
import com.yanqu.road.logic.helper.PowerHelper;
import com.yanqu.road.pb.activity.GoddessProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.manger.ServerLanguageMgr;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.goddess.GoddessMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

public class GoddessModule extends GeneralModule {

    private GoddessUserData userData;

    public GoddessModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        ActivityInfo activityInfo = GoddessMgr.getActivityInfo();
        if(ActivityMgr.activityInShowTime(activityInfo)) {
            userData = new GoddessUserDataDaoImpl().getGoddessUserData(activityInfo.getActivityId(), player.getUserId());
        }
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if(this.userData != null){
            if(this.userData.isInsertOption()){
                new GoddessUserDataDaoImpl().add(userData);
            }else if(this.userData.isUpdateOption()){
                new GoddessUserDataDaoImpl().update(userData);
            }
        }
        return true;
    }


    @Override
    public void afterLogin() {
        activityReload();
    }

    public void activityReload() {
        if (!SystemOpenMgr.systemOpen(player, eSystemId.GoddessActivityId.getValue())) {
            return;
        }

        GoddessConfig config = GoddessMgr.getConfig();
        if(config == null || !ActivityMgr.activityInShowTime(config.getActivityInfo())){
            return;
        }

        syncConfig(config);

        initUserData(config);

        if(!resetOneDay()) {
            syncUserData(config);
        }
    }

    private void syncConfig(GoddessConfig config) {

        GoddessProto.GoddessActivityConfigSync.Builder syncMsg = GoddessProto.GoddessActivityConfigSync.newBuilder();
        for (GoddessMissionInfo missionInfo : config.getMissionInfoList()) {
            GoddessProto.GoddessActivityMissionInfoTemp.Builder builder = GoddessPb.buildMission(missionInfo, player.getLanguage());
            syncMsg.addMission(builder);
        }
        for (GoddessRandomStoneInfo shapeInfo : config.getShapeInfoList()) {
            GoddessProto.GoddessRandomShapeInfoTemp.Builder builder = GoddessPb.buildShapeInfo(shapeInfo, player.getLanguage());
            syncMsg.addShape(builder);
        }
        for (GoddessLiangYiStoneInfo stoneInfo : config.getLiangYiStoneInfoList()) {
            GoddessProto.GoddessLiangYiStoneInfoTemp.Builder builder = GoddessPb.buildLiangYiStone(stoneInfo, player.getLanguage());
            syncMsg.addLiangYi(builder);
        }
        for (GoddessEraInfo eraInfo : config.getEraInfoList()) {
            GoddessProto.GoddessEraInfoTemp.Builder builder = GoddessPb.buildEarInfo(eraInfo, player.getLanguage());
            syncMsg.addEraInfo(builder);
        }
        for (GoddessPeopleInfo peopleInfo : config.getPeopleInfoList()) {
            GoddessProto.GoddessPeopleInfoTemp.Builder builder = GoddessProto.GoddessPeopleInfoTemp.newBuilder();
            builder.setPeopleId(peopleInfo.getPeopleId());
            builder.setName(ServerLanguageMgr.getContent(peopleInfo.getName(), player.getLanguage()));
            builder.setDesc(ServerLanguageMgr.getContent(peopleInfo.getDesc(), player.getLanguage()));
            builder.setWeight(peopleInfo.getWeight());
            syncMsg.addPeople(builder);
        }
        for (GoddessPeoBookInfo bookInfo : config.getBookInfoList()) {
            GoddessProto.GoddessPeoBookInfoTemp.Builder builder = GoddessProto.GoddessPeoBookInfoTemp.newBuilder();
            builder.setBookId(bookInfo.getBookId());
            builder.setComb(bookInfo.getComb());
            builder.setCombName(ServerLanguageMgr.getContent(bookInfo.getCombName(), player.getLanguage()));
            syncMsg.addBook(builder);
        }
        player.sendPacket(Protocol.U_GODDESS_SYNC_CONFIG, syncMsg);

    }

    private synchronized void initUserData(GoddessConfig config) {

        if(userData == null || userData.getActivityId() != config.getActivityInfo().getActivityId()){

            GoddessUserData tempData = new GoddessUserData();
            tempData.setUserId(player.getUserId());
            tempData.setActivityId(config.getActivityInfo().getActivityId());
            tempData.setInsertOption();
            tempData.setLastEnergyRecTime(System.currentTimeMillis());

            GoddessEraInfo firstEra = config.getEraInfoList().get(0);
            tempData.setEnergy(firstEra.getEnergyMax());
            tempData.setEra(firstEra.getEraId());

            tempData.setColorStoneMap(new HashMap<>());
            tempData.setYinStoneList(new ArrayList<>());
            tempData.setYangStoneList(new ArrayList<>());
            tempData.setPeoMap(new HashMap<>());
            tempData.setHistoryMap(new HashMap<>());
            tempData.setPassMissNum(1);

            //最高记录
            tempData.setRankCellList(new ArrayList<>());
            tempData.setRankColorStoneMap(new HashMap<>());
            tempData.setRankYangStoneList(new ArrayList<>());
            tempData.setRankYinStoneList(new ArrayList<>());

            GoddessYearStatus yearStatus = new GoddessYearStatus();
            GoddessMissionInfo missionInfo = config.getMissionInfoList().get(0);
            yearStatus.setMissionId(missionInfo.getMissionId());
            tempData.setYearStatus(yearStatus);

            List<GoddessCell> cellList = new ArrayList<>();
            int cellNum = config.COLUMN_NUM * config.ROW_NUM;
            for (int i = 0; i < cellNum; i++) {
                GoddessCell cell = new GoddessCell(i);
                cellList.add(cell);
            }
            tempData.setCellList(cellList);

            //解锁格子
            for (int pos : getLandInfo(missionInfo.getLandInfo(), config)) {
                GoddessCell cell = tempData.getCellList().get(pos);
                cell.setOpen(1);
            }


            tempData.setInsertOption();
            userData = tempData;

        }
    }

    private void syncUserData(GoddessConfig config) {

        if(userData != null) {
            GoddessMissionInfo missionInfo = config.getGoddessMissionInfo(userData.getYearStatus().getMissionId());
            GoddessEraInfo eraInfo = config.getGoddessEraInfo(userData.getEra());
            recoverUserEnergyPower(eraInfo.getEnergyResume(), eraInfo.getEnergyMax());

            GoddessProto.GoddessUserDataSync.Builder syncMsg = GoddessProto.GoddessUserDataSync.newBuilder();
            syncMsg.setUserData(GoddessPb.buildUserData(userData));
            player.sendPacket(Protocol.U_GODDESS_SYNC_USER_DATA, syncMsg);
        }
    }

    /**
     * 体力恢复
     */
    public void recoverUserEnergyPower(int recoverDuration, int maxPower) {
        if (userData == null || GoddessMgr.getConfig() == null) {
            return;
        }
        int beforeVal = userData.getEnergy();
        GoddessConfig config = GoddessMgr.getConfig();
        CalcPowerResult calcPowerResult = PowerHelper.calcPower(userData.getLastEnergyRecTime() / 1000,
                recoverDuration , config.getAuraGetNum(), maxPower, userData.getEnergy());

        userData.setEnergy(calcPowerResult.getCurPower());
        userData.setLastEnergyRecTime(calcPowerResult.getLastRecoverTime() * 1000);

        if(beforeVal != userData.getEnergy()){
            AutoLogMgr.add(new LogGoddessEnergy(player.getUserId(), userData.getActivityId(), 2,
                    userData.getEnergy() - beforeVal,
                    userData.getEnergy(),
                    userData.getEra(),
                    userData.getYearStatus().getMissionId()));
        }
    }

    /**
     * 扣体力
     */
    public boolean reduceEnergy(int count, int type) {
        if (userData.getEnergy() < count)
            return false;

        GoddessConfig config = GoddessMgr.getConfig();
        GoddessEraInfo eraInfo = config.getGoddessEraInfo(userData.getEra());
        boolean aboveMaxBefore = userData.getEnergy() >= eraInfo.getEnergyMax();

        userData.setEnergy(userData.getEnergy() - count);

        if (aboveMaxBefore) {
            userData.setLastEnergyRecTime(System.currentTimeMillis());
        }

        // 日志
        AutoLogMgr.add(new LogGoddessEnergy(userData.getUserId(), userData.getActivityId(),
                type, count, userData.getEnergy(),
                userData.getEra(),
                userData.getYearStatus().getMissionId()));
        return true;
    }

    private boolean resetOneDay() {
        return false;
    }

    public int getUserData2() {
        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        GoddessConfig config = GoddessMgr.getConfig();
        //当前纪元
        GoddessEraInfo eraInfo = config.getGoddessEraInfo(userData.getEra());
        recoverUserEnergyPower(eraInfo.getEnergyResume(), eraInfo.getEnergyMax());

        GoddessProto.GoddessGetUserDataRespMsg.Builder respMsg = GoddessProto.GoddessGetUserDataRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUserData(GoddessPb.buildUserData(userData));
        player.sendPacket(Protocol.U_GODDESS_GET_USER_DATA, respMsg);
        return 0;
    }

    /**
     * 造人
     */
    public int makePeople() {

        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        GoddessConfig config = GoddessMgr.getConfig();

        //当前重天
        GoddessMissionInfo missionInfo = config.getGoddessMissionInfo(userData.getYearStatus().getMissionId());

        //当前纪元
        GoddessEraInfo eraInfo = config.getGoddessEraInfo(userData.getEra());

        //体力是否足够
        recoverUserEnergyPower(eraInfo.getEnergyResume(), eraInfo.getEnergyMax());
        if(userData.getEnergy() < eraInfo.getEnergyCost()){
            return GameErrorCode.E_GODDESS_ENERGY_NO_ENOUGH;
        }

        //五彩石背包上限
        if(config.getBagMaxNumStone() <= getBagColorStoneNum(userData)){
            return GameErrorCode.E_GODDESS_COLOR_STONE_MAX_LIMIT;
        }

        //扣体力
        reduceEnergy(eraInfo.getEnergyCost(), 1);
        userData.setMakeYear(1 + userData.getMakeYear());

        long score = eraInfo.getEnergyCost() * config.getEnergyScoreNum();
        //积分
        userData.setScore(userData.getScore() + score);

        String scoreReward = PropertyHelper.parseGoodsToString(config.getScoreItemId(), BigInteger.valueOf(score));
        player.getModule(CurrencyModule.class).addCurrency(scoreReward, eLogMoneyType.GoddessActivity, eLogMoneyType.GoddessMakePeoReward);

        long oldHuman = userData.getHumanNum();

        //造人结果
        GoddessProto.GoddessMakePeopleResultTemp.Builder resultBuilder = GoddessProto.GoddessMakePeopleResultTemp.newBuilder();

        Random random = new Random();
        //随机获得小人
        List<Integer> getPeoList = randomPeople(userData, config, eraInfo, new Random());

        long addUp = missionInfo.getPeopleUpParam() + eraInfo.getPeopleUpParam() + getPeoList.size();
        //最后人数
        userData.setHumanNum(userData.getHumanNum() + addUp);

        //人数增长
        addHistory(userData, eraInfo, 2, userData.getHumanNum() - oldHuman);

        resultBuilder.setPeopleUp(userData.getHumanNum() - oldHuman);
        resultBuilder.setMakePeople(0);

        for (int peoId : getPeoList) {
            int oldNum = userData.getPeoMap().getOrDefault(peoId, 0);
            userData.getPeoMap().put(peoId, oldNum + 1);
            if(oldNum == 0){
                //纪元史，所赐解锁小人
                addHistory(userData, eraInfo, 1, peoId);
            }
            player.notifyListener(eGamePlayerEventType.GoddessPeoUnlock.getValue(), new ValueFourParamArgs(BigInteger.valueOf(userData.getPeoMap().get(peoId)), peoId));
        }
        resultBuilder.addAllPeoId(getPeoList);

        //随机获得五彩石
        //石头形状id
        List<Integer> stoneList = randomStone(config, eraInfo, missionInfo, random);
        //石头id
        List<Integer> stoneIdList = new ArrayList<>();
        List<Long> stonePointList = new ArrayList<>();
        Map<Integer, GoddessColorStone> addStoneMap = new HashMap<>();
        if(userData.getMakeYear() <= config.getGuideList().size()){
            String guideInfo = config.getGuideList().get(userData.getMakeYear() - 1);
            List<String> guideInfoList = StringUtils.stringToStringList(guideInfo, ";");
            for (String itemInfo : guideInfoList) {
                List<Integer> itemInfoList = StringUtils.stringToIntegerList(itemInfo, "=");
                Map<Integer, GoddessColorStone> tempMap = addColorStoneToBag(userData, itemInfoList.get(0), itemInfoList.get(2), config, itemInfoList.get(1));
                stonePointList.add((long)itemInfoList.get(2));
                for (Map.Entry<Integer, GoddessColorStone> stoneEntry : tempMap.entrySet()) {
                    stoneIdList.add(stoneEntry.getValue().getId());
                }
                addStoneMap.putAll(tempMap);
            }
        }else {
            for (int i = 0; i < stoneList.size(); i++) {
                long pointAddition = getPointAddition(config, eraInfo, random);
                int shapeId = stoneList.get(i);
                //随机点数
                long basePoint = randomBasePoint(config, random);
                GoddessRandomStoneInfo stoneInfo = config.getGoddessRandomStoneInfo(shapeId);
                long point = BigDecimal.valueOf(basePoint).multiply(BigDecimal.valueOf(pointAddition)).multiply(BigDecimal.valueOf(stoneInfo.getShapePoint())).divide(BigDecimal.valueOf(1000 * 1000), 0, BigDecimal.ROUND_UP).longValue();
                stonePointList.add(point);
                //GoddessMgr.getLogger().info("goddess point : {} -> {}， base point {}, pointAddition {}", basePoint, point, basePoint, pointAddition);
                int rotate = random.nextInt(4);
                Map<Integer, GoddessColorStone> tempMap = addColorStoneToBag(userData, shapeId, point, config, rotate);
                for (Map.Entry<Integer, GoddessColorStone> stoneEntry : tempMap.entrySet()) {
                    stoneIdList.add(stoneEntry.getValue().getId());
                }
                addStoneMap.putAll(tempMap);
            }
        }
        for (Map.Entry<Integer, GoddessColorStone> stoneEntry : addStoneMap.entrySet()) {
            resultBuilder.addColorStone(GoddessPb.buildColorStoneData(stoneEntry.getValue()));
        }

        //下一年
        userData.getYearStatus().setYearOfEar(1 + userData.getYearStatus().getYearOfEar());

        List<GoddessYinYangStone> yiLiangList = null;

        //下一纪元
        GoddessEraInfo nextEraInfo = config.getGoddessEraInfo(userData.getEra() + 1);
        if(nextEraInfo != null){
            //是否进入新纪元
            if(userData.getHumanNum() >= Long.parseLong(nextEraInfo.getUpNeed())){
                userData.setEra(nextEraInfo.getEraId());
                userData.getYearStatus().setYearOfEar(1);
                //其他奖励
                yiLiangList = addEraReward(userData, config, nextEraInfo);
                resultBuilder.setEraReward(nextEraInfo.getEraReward());
            }
        }

        GoddessProto.GoddessMakePeopleRespMsg.Builder respMsg = GoddessProto.GoddessMakePeopleRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUserData(GoddessPb.buildUserData(userData));
        respMsg.setResult(resultBuilder);
        player.sendPacket(Protocol.U_GODDESS_MAKE_PEOPLE, respMsg);


        //图鉴组合成就
        for (GoddessPeoBookInfo bookInfo : config.getBookInfoList()) {
            List<Integer> list = StringUtils.stringToIntegerList(bookInfo.getComb(), "\\|");
            boolean comb = true;
            for (int peo : list) {
                if(!userData.getPeoMap().containsKey(peo)){
                    comb = false;
                    break;
                }
            }
            if(comb){
                player.notifyListener(eGamePlayerEventType.GoddessPeoCombProgress.getValue(), new ValueFourParamArgs(BigInteger.ONE, bookInfo.getBookId()));
            }
        }

        //日志
        AutoLogMgr.add(new LogGoddessMakePeople(
                player.getUserId(),
                userData.getActivityId(),
                eraInfo.getEraId(),
                missionInfo.getMissionId(),
                addUp,
                StringUtils.listToString(getPeoList, ","),
                (yiLiangList == null || yiLiangList.size() == 0) ? "" : JSON.toJSONString(yiLiangList)
        ));

        if(stoneList.size() > 0) {
            AutoLogMgr.add(new LogGoddessColorStone(
                    player.getUserId(),
                    userData.getActivityId(),
                    eraInfo.getEraId(),
                    missionInfo.getMissionId(),
                    1, //get
                    StringUtils.listToString(stoneIdList, ","),
                    StringUtils.listToString(stonePointList, ",")
            ));
        }
        return 0;
    }

    /**
     * 添加纪元史
     * @param eraInfo 纪元
     * @param type 类型：1：图鉴解锁，2：人类新增（汇总），3：补天成功
     * @param val 值
     */
    private void addHistory(GoddessUserData userData, GoddessEraInfo eraInfo, int type, long val) {
        if(!userData.getHistoryMap().containsKey(eraInfo.getEraId())){
            userData.getHistoryMap().put(eraInfo.getEraId(), new ArrayList<>());
        }
        if(type == 2) {
            GoddessEraHistory history = null;
            for (GoddessEraHistory temp : userData.getHistoryMap().get(eraInfo.getEraId())) {
                if (temp.getType() == type) {
                    history = temp;
                }
            }
            if (history == null) {
                history = new GoddessEraHistory();
                userData.getHistoryMap().get(eraInfo.getEraId()).add(history);
                history.setEraId(eraInfo.getEraId());
                history.setType(type);
            }
            history.setVal(history.getVal() + val);
        }else {
            GoddessEraHistory history = new GoddessEraHistory();
            history.setEraId(eraInfo.getEraId());
            history.setType(type);
            history.setVal(val);
            history.setTime(DateHelper.getCurrentSecond());
            userData.getHistoryMap().get(eraInfo.getEraId()).add(history);
        }
    }


    /**
     * 使用体力道具
     */
    public int useEnergyGoods(int count) {
        if (count <= 0 || count > 99999) {
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        GoddessConfig config = GoddessMgr.getConfig();
        Property cost = new Property();
        cost.addProperty(config.getEnergyRecItemId(), BigInteger.valueOf(count));

        GoddessEraInfo eraInfo = config.getGoddessEraInfo(userData.getEra());

        // 计算恢复数量
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(config.getEnergyRecItemId());
        BigInteger energyCount = goodsInfo.getParamList().get(0);
        int totalCount = energyCount.intValue() * count;

        // 扣道具
        if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.GoddessActivity, eLogMoneyType.GoddessUseEnergyItemCost)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        // 加体力
        userData.setEnergy(userData.getEnergy() + totalCount);

        if (userData.getEnergy() > eraInfo.getEnergyMax()) {
            userData.setLastEnergyRecTime(System.currentTimeMillis());
        }

        GoddessProto.GoddessUseStoneGoodsRespMsg.Builder builder = GoddessProto.GoddessUseStoneGoodsRespMsg.newBuilder();
        builder.setRet(0);
        builder.setPower(userData.getEnergy());
        builder.setLastRecoverTime(userData.getLastEnergyRecTime());
        player.sendPacket(Protocol.U_GODDESS_ITEM_RECOVER_ENERGY, builder);

        // 日志
        AutoLogMgr.add(new LogGoddessEnergy(userData.getUserId(), userData.getActivityId(),
                3, count, userData.getEnergy(),
                userData.getEra(),
                userData.getYearStatus().getMissionId()));
        return 0;
    }

    /**
     * 格子镶嵌
     * @param pos 目标起始位置
     * @param stoneId 五彩石
     *
     */
    public int cellInlay(int pos, int stoneId) {
        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        //位置有效
        GoddessConfig config = GoddessMgr.getConfig();
        if(pos < 0 || pos > config.ROW_NUM * config.COLUMN_NUM - 1){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        GoddessMissionInfo missionInfo = config.getGoddessMissionInfo(userData.getYearStatus().getMissionId());
        GoddessEraInfo eraInfo = config.getGoddessEraInfo(userData.getEra());
        GoddessColorStone colorStone = userData.getColorStoneMap().get(stoneId);
        if(colorStone == null){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        //旧位置
        int colorStoneOldPos = colorStone.getCell();

        //目标格子是否解锁
        GoddessCell targetCell = userData.getCellList().get(pos);
        if(targetCell.getOpen() == 0){
            return GameErrorCode.E_GODDESS_CELL_LOCK;
        }

        GoddessRandomStoneInfo shapeInfo = config.getGoddessRandomStoneInfo(colorStone.getSd());
        if(shapeInfo == null){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        int oldStoneId = targetCell.getStoneId();
        GoddessColorStone oldStone = userData.getColorStoneMap().get(oldStoneId);
        //目标格子有其他五彩石
        if(oldStoneId > 0 && oldStoneId != stoneId){
            //形状是否相同
            GoddessRandomStoneInfo oldShape = config.getGoddessRandomStoneInfo(oldStone.getSd());
            if(oldShape.getShapeId() != shapeInfo.getShapeId()) {
                return GameErrorCode.E_GODDESS_CELL_INLAY_SHAPE_DIFFERENT;
            }
        }

        if(pos == colorStone.getCell()){
            //无需替换
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        //新位置，可以嵌入的所有位置
        List<Integer> targetPosList = GoddessMgr.getInLayPositionList(pos, colorStone.getFs(), config);
        if(targetPosList.size() == 0){
            return GameErrorCode.E_GODDESS_CELL_INLAY_POSITION_ERROR;
        }

        for (int position : targetPosList) {
            if(position < 0 || position > config.ROW_NUM * config.COLUMN_NUM - 1){
                return GameErrorCode.E_GODDESS_CELL_INLAY_POSITION_ERROR;
            }
            if(position > userData.getCellList().size() - 1){
                return GameErrorCode.E_GODDESS_CELL_INLAY_POSITION_ERROR;
            }
            //新位置集合是否解锁
            GoddessCell tempCell = userData.getCellList().get(position);
            if(tempCell.getOpen() == 0){
                return GameErrorCode.E_GODDESS_CELL_LOCK;
            }
        }

        //移格子，不能与其他重叠
        for (int position : targetPosList) {
            GoddessCell tempCell = userData.getCellList().get(position);
            if(tempCell.getStoneId() != oldStoneId && tempCell.getStoneId() > 0 && oldStoneId > 0){
                return GameErrorCode.E_GODDESS_CELL_INLAY_POSITION_ERROR;
            }
        }

        if(colorStoneOldPos > -1){
            //可能是替换
            for (int p : targetPosList) {
                GoddessCell tempCell = userData.getCellList().get(p);
                if(tempCell.getStoneId() > 0 && (tempCell.getStoneId() != stoneId && tempCell.getStoneId() != oldStoneId)){
                    return GameErrorCode.E_GODDESS_CELL_INLAY_POSITION_ERROR;
                }
            }
            //清除之前的嵌入
            colorStone.setCell(-1);
            for (GoddessCell tempCell : userData.getCellList()) {
                if(tempCell.getStoneId() == stoneId){
                    tempCell.setStoneId(0);
                 }
            }
        }

        //交换位置
        if(oldStoneId > 0){
            if(colorStoneOldPos > -1){
                //交换到位置上
                if(stoneId != oldStoneId){
                    List<Integer> tempPosList = GoddessMgr.getInLayPositionList(colorStoneOldPos, oldStone.getFs(), config);
                    oldStone.setCell(colorStoneOldPos);
                    for (int position : tempPosList) {
                        GoddessCell tempCell = userData.getCellList().get(position);
                        tempCell.setStoneId(oldStoneId);
                    }
                }
            }else {
                //直接清除原来的
                oldStone.setCell(-1);
            }
        }


        //新嵌入
        for (int position : targetPosList) {
            GoddessCell tempCell = userData.getCellList().get(position);
            tempCell.setStoneId(colorStone.getId());
        }
        colorStone.setCell(pos);

        userData.setCellPoint(calCellAdditionPoint(userData, config));

        GoddessProto.GoddessCellInlayRespMsg.Builder respMsg = GoddessProto.GoddessCellInlayRespMsg.newBuilder().setRet(0);

        player.notifyListener(eGamePlayerEventType.GoddessMissionRank.getValue(), new ValueParamArgs(userData.getPassMissNum(), "" + userData.getCellPoint()));
        recordRankData();

        GoddessProto.GoddessUserDataTemp.Builder buildUserData = GoddessPb.buildUserData(userData);

        respMsg.setUserData(buildUserData);
        player.sendPacket(Protocol.U_GODDESS_CELL_INLAY, respMsg);
        return 0;
    }

    private String finishMission(GoddessConfig config, GoddessMissionInfo missionInfo, GoddessEraInfo eraInfo) {
        GoddessMissionInfo next = config.getGoddessMissionInfo(missionInfo.getMissionId() + 1);
        List<Integer> stoneIdList = new ArrayList<>();
        List<Long> stonePointList = new ArrayList<>();
        long old = userData.getCellPoint();
        if(next != null){
            userData.getYearStatus().setMissionId(next.getMissionId());
            for (GoddessCell cell : userData.getCellList()) {
                cell.setOpen(0);
            }
            for (int p : getLandInfo(next.getLandInfo(), config)) {
                GoddessCell c = userData.getCellList().get(p);
                c.setOpen(1);
            }
            userData.setPassMissNum(1 + userData.getPassMissNum());
            //补天完成
            addHistory(userData, eraInfo, 3, missionInfo.getMissionId());
            //清除石头（消耗）
            Set<Integer> stoneList = new HashSet<>();
            for (GoddessCell goddessCell : userData.getCellList()) {
                if(goddessCell.getStoneId() > 0){
                    stoneList.add(goddessCell.getStoneId());
                    goddessCell.setStoneId(0);
                }
            }
            for (int sid : stoneList) {
                stoneIdList.add(sid);
                GoddessColorStone remove = userData.getColorStoneMap().remove(sid);
                if(remove != null){
                    stonePointList.add(remove.getPt());
                }
            }
            player.notifyListener(eGamePlayerEventType.GoddessMissionProgress.getValue(), userData.getPassMissNum() - 1);

            userData.setCellPoint(calCellAdditionPoint(userData, config));

        }else {
            //最后关卡，过关，一直刷排行
            if(userData.getPassMissNum() < config.getMissionInfoList().size()){
                userData.setPassMissNum(userData.getPassMissNum() + 1);
            }
            if(userData.getPassMissNum() == config.getMissionInfoList().size()){
                player.notifyListener(eGamePlayerEventType.GoddessMissionProgress.getValue(), config.getMissionInfoList().size());
            }
            userData.setCellPoint(calCellAdditionPoint(userData, config));

        }

        if(missionInfo.getMissionId() > userData.getYearStatus().getMaxMissId()){
            player.getModule(CurrencyModule.class).addCurrency(missionInfo.getReward(), eLogMoneyType.GoddessActivity, eLogMoneyType.GoddessMissionReward);
            userData.getYearStatus().setMaxMissId(missionInfo.getMissionId());

            //日志
            AutoLogMgr.add(new LogGoddessMission(
                    player.getUserId(),
                    userData.getActivityId(),
                    eraInfo.getEraId(),
                    missionInfo.getMissionId(),
                    old
            ));

            //石头消耗
            AutoLogMgr.add(new LogGoddessColorStone(
                    player.getUserId(),
                    userData.getActivityId(),
                    eraInfo.getEraId(),
                    missionInfo.getMissionId(),
                    4, //补天消耗
                    StringUtils.listToString(stoneIdList, ","),
                    StringUtils.listToString(stonePointList, ",")

            ));

            return missionInfo.getReward();
        }
        return "";
    }

    private boolean passMission(GoddessConfig config, GoddessMissionInfo missionInfo, GoddessEraInfo eraInfo) {
        //扫描格子，是否补天完成
        boolean finish = userData.getCellPoint() >= new BigInteger(missionInfo.getTargetPoint()).longValue();
        for (GoddessCell goddessCell : userData.getCellList()) {
            if(goddessCell.getOpen() == 1 && goddessCell.getStoneId() == 0){
                finish = false;
                break;
            }
        }
        return finish;
    }

    //改变时记录
    private void recordRankData(){

        if(userData == null){
            return;
        }
        if(userData.getCellPoint() > userData.getRankCellPoint()){

            userData.setRankEra(userData.getEra());
            userData.setRankCellPoint(userData.getCellPoint());

            List<GoddessCell> cellList = new ArrayList<>();
            for (GoddessCell cell : userData.getCellList()) {
                cellList.add(GoddessMgr.copyCell(cell));
            }

            Map<Integer, GoddessColorStone> colorStoneMap = new HashMap<>();
            for (Map.Entry<Integer, GoddessColorStone> entry : userData.getColorStoneMap().entrySet()) {
                GoddessColorStone stone = entry.getValue();
                if(stone.getCell() > -1){
                    colorStoneMap.put(stone.getId(), GoddessMgr.copyGoddessColorStone(stone));
                }
            }

            List<GoddessYinYangStone> list = new ArrayList<>();
            for (GoddessYinYangStone yinYangStone : userData.getYinStoneList()) {
                if(yinYangStone.getPos() > -1) {
                    list.add(GoddessMgr.copyGoddessYinYangStone(yinYangStone));
                }
            }

            List<GoddessYinYangStone> list2 = new ArrayList<>();
            for (GoddessYinYangStone yinYangStone : userData.getYangStoneList()) {
                if(yinYangStone.getPos() > -1) {
                    list2.add(GoddessMgr.copyGoddessYinYangStone(yinYangStone));
                }
            }

            userData.setRankYinStoneList(list);
            userData.setRankYangStoneList(list2);
            userData.setRankCellList(cellList);
            userData.setRankColorStoneMap(colorStoneMap);
        }
    }

    //过关重置
    private void resetRankData(){
        if(userData != null){

            userData.setRankEra(userData.getEra());
            userData.setRankCellPoint(userData.getCellPoint());

            userData.setRankCellList(userData.getCellList());
            userData.setRankColorStoneMap(new HashMap<>());
            userData.setRankYinStoneList(new ArrayList<>());
            userData.setRankYangStoneList(new ArrayList<>());

        }
    }



    /**
     * 取消格子镶嵌
     */
    public int cancelCellInlay(int stoneId){
        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        GoddessConfig config = GoddessMgr.getConfig();

        GoddessColorStone colorStone = userData.getColorStoneMap().get(stoneId);
        if(colorStone == null || colorStone.getCell() < 0){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        colorStone.setCell(-1);
        for (GoddessCell cell : userData.getCellList()) {
            if(cell.getStoneId() == stoneId){
                cell.setStoneId(0);
            }
        }
        userData.setUpdateOption();
        userData.setCellPoint(calCellAdditionPoint(userData, config));

        GoddessProto.GoddessCancelCellInlayRespMsg.Builder respMsg = GoddessProto.GoddessCancelCellInlayRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUserData(GoddessPb.buildUserData(userData));
        player.sendPacket(Protocol.U_GODDESS_CANCEL_CELL_INLAY, respMsg);
        return 0;
    }

    /**
     * 五彩石洗练
     */
    public int stoneXiLian(List<Integer> idList) {
        if(idList.size() != 2){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        int idOne = idList.get(0);
        int idTwo = idList.get(1);
        if(idOne == idTwo){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }
        GoddessConfig config = GoddessMgr.getConfig();
        GoddessMissionInfo missionInfo = config.getGoddessMissionInfo(userData.getYearStatus().getMissionId());

        GoddessColorStone stoneOne = userData.getColorStoneMap().get(idOne);
        GoddessColorStone stoneTwo = userData.getColorStoneMap().get(idTwo);
        if(stoneOne == null || stoneTwo == null){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        if(stoneTwo.getCell() > -1){
            return GameErrorCode.E_GODDESS_STONE_IN_CELL;
        }

        GoddessRandomStoneInfo shapeOne = config.getGoddessRandomStoneInfo(stoneOne.getSd());
        GoddessRandomStoneInfo shapeTow = config.getGoddessRandomStoneInfo(stoneTwo.getSd());
        if(shapeOne.getShapeType() != shapeTow.getShapeType()){
            return GameErrorCode.E_GODDESS_STONE_NOT_SAME_TYPE;
        }

        GoddessEraInfo eraInfo = config.getGoddessEraInfo(userData.getEra());
        //随机点数
        Random random = new Random();
        long basePoint = randomBasePoint(config, random);
        long pointAddition = getPointAddition(config, eraInfo, random);
        long point = BigDecimal.valueOf(basePoint).multiply(BigDecimal.valueOf(pointAddition)).multiply(BigDecimal.valueOf(shapeOne.getShapePoint())).divide(BigDecimal.valueOf(1000 * 1000), 0, BigDecimal.ROUND_UP).longValue();
        //GoddessMgr.getLogger().info("goddess point : {} -> {}， base point {}, pointAddition {}", stoneOne.getPoint(), point, basePoint, pointAddition);
        if(userData.getYearStatus().getXiLian() == 0 && userData.getYearStatus().getMissionId() <= 1003){
            point = Long.valueOf(config.getGoddessMissionInfo(userData.getYearStatus().getMissionId()).getTargetPoint());
        }
        if(point > stoneOne.getPt()) {
            stoneOne.setPt(point);
        }
        //消耗洗练的五彩石
        userData.getColorStoneMap().remove(stoneTwo.getId());
        userData.getYearStatus().setXiLian(1 + userData.getYearStatus().getXiLian());

        GoddessProto.GoddessColorStoneXiLianRespMsg.Builder respMsg = GoddessProto.GoddessColorStoneXiLianRespMsg.newBuilder().setRet(0);
        if(stoneOne.getCell() > -1){
            userData.setCellPoint(calCellAdditionPoint(userData, config));
            player.notifyListener(eGamePlayerEventType.GoddessMissionRank.getValue(), new ValueParamArgs(userData.getPassMissNum(), "" + userData.getCellPoint()));
            recordRankData();
        }

        userData.setUpdateOption();

        GoddessProto.GoddessUserDataTemp.Builder buildUserData = GoddessPb.buildUserData(userData);
        respMsg.setUserData(buildUserData);
        respMsg.setNewPoint(point);
        respMsg.addColorStone(GoddessPb.buildColorStoneData(stoneOne));
        player.sendPacket(Protocol.U_GODDESS_COLOR_STONE_XILIAN, respMsg);

        //日志
        AutoLogMgr.add(new LogGoddessColorStone(
                player.getUserId(),
                userData.getActivityId(),
                eraInfo.getEraId(),
                missionInfo.getMissionId(),
                2, // remove
                stoneTwo.getId() + "",
                stoneTwo.getPt() + ""
        ));
        AutoLogMgr.add(new LogGoddessColorStone(
                player.getUserId(),
                userData.getActivityId(),
                eraInfo.getEraId(),
                missionInfo.getMissionId(),
                3, //change
                stoneOne.getId() + "",
                stoneOne.getPt() + ""
                ));
        return 0;
    }

    private long getPointAddition(GoddessConfig config, GoddessEraInfo eraInfo, Random random) {
        List<Long> pointParamList = StringUtils.stringToLongList(eraInfo.getPointParam(), "\\|");
        //纪元点数千分比
        long pointAddition = pointParamList.get(0);
        //只配置一个数
        if(pointParamList.size() == 1){
            return pointAddition;
        }
        if(pointParamList.get(0).longValue() == pointParamList.get(1).longValue()){
            return pointAddition;
        }
        //范围超了
        if(pointAddition > Integer.MAX_VALUE || pointParamList.get(1) > Integer.MAX_VALUE){
            //先降低，会失去一定精度
            long down = 10000;
            pointAddition = pointParamList.get(0) + random.nextInt((int)((pointParamList.get(1) - pointParamList.get(0)) / down)) * down;
        }else {
            pointAddition = pointParamList.get(0) + random.nextInt((int)(pointParamList.get(1) - pointParamList.get(0)));
        }
        return pointAddition;
    }

    /**
     * 两仪石镶嵌
     */
    public int yingYangInlay(int pos, int stoneId, int type){
        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        GoddessConfig config = GoddessMgr.getConfig();
        if(pos < 0 || pos > config.COLUMN_NUM - 1){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        GoddessYinYangStone oldStone = null;
        if(type == 0){
            //格子是否解锁
            boolean open = false;
            for (int i = 0; i < config.ROW_NUM; i++) {
                int index = GoddessMgr.getIndex(new Position(pos, i), config);
                GoddessCell cell = userData.getCellList().get(index);
                if(cell.getOpen() == 1){
                    open = true;
                    break;
                }
            }
            if(!open) {
                return GameErrorCode.E_GODDESS_CELL_LOCK;
            }
            for (GoddessYinYangStone yinYangStone : userData.getYinStoneList()) {
                if(yinYangStone.getPos() == pos){
                    oldStone = yinYangStone;
                }
            }
        }else if(type == 1){
            boolean open = false;
            for (int i = 0; i < config.COLUMN_NUM; i++) {
                int index = GoddessMgr.getIndex(new Position(i, pos), config);
                GoddessCell cell = userData.getCellList().get(index);
                if(cell.getOpen() == 1){
                    open = true;
                    break;
                }
            }
            if(!open) {
                return GameErrorCode.E_GODDESS_CELL_LOCK;
            }
            for (GoddessYinYangStone yinYangStone : userData.getYangStoneList()) {
                if(yinYangStone.getPos() == pos){
                    oldStone = yinYangStone;
                }
            }
        }

        GoddessYinYangStone yinYangStone = getGoddessYinYangStone(userData, stoneId, type);
        if(yinYangStone == null){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        if(yinYangStone.getPos() == pos){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        int stoneOldPos = yinYangStone.getPos();
        yinYangStone.setPos(pos);

        //被替换的石头
        if(oldStone != null){
            oldStone.setPos(stoneOldPos);
        }

        userData.setUpdateOption();
        userData.setCellPoint(calCellAdditionPoint(userData, config));

        player.notifyListener(eGamePlayerEventType.GoddessMissionRank.getValue(), new ValueParamArgs(userData.getPassMissNum(), "" + userData.getCellPoint()));
        recordRankData();

        GoddessProto.GoddessYinYangInlayRespMsg.Builder respMsg = GoddessProto.GoddessYinYangInlayRespMsg.newBuilder();

        GoddessProto.GoddessUserDataTemp.Builder buildUserData = GoddessPb.buildUserData(userData);
        respMsg.setRet(0);
        respMsg.setUserData(buildUserData);
        player.sendPacket(Protocol.U_GODDESS_YING_YANG_INLAY, respMsg);
        return 0;
    }

    /**
     * 取消两仪石镶嵌
     */
    public int cancelYingYangInlay(int pos, int stoneId, int type){
        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }
        GoddessConfig config = GoddessMgr.getConfig();
        if(pos < 0 || pos > config.ROW_NUM - 1){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        GoddessYinYangStone yinYangStone = getGoddessYinYangStone(userData, stoneId, type);
        if(yinYangStone == null){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        if(yinYangStone.getPos() < 0 || pos != yinYangStone.getPos()){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        yinYangStone.setPos(-1);
        userData.setUpdateOption();
        userData.setCellPoint(calCellAdditionPoint(userData, config));

        GoddessProto.GoddessCancelYinYangInlayRespMsg.Builder respMsg = GoddessProto.GoddessCancelYinYangInlayRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUserData(GoddessPb.buildUserData(userData));
        player.sendPacket(Protocol.U_GODDESS_CANCEL_YING_YANG_INLAY, respMsg);

        return 0;
    }


    /**
     * 纪元史
     */
    public int syncHistory() {

        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        GoddessProto.GetGoddessEraHistoryRespMsg.Builder respMsg = GoddessProto.GetGoddessEraHistoryRespMsg.newBuilder();
        //纪元历史
        for (Map.Entry<Integer, List<GoddessEraHistory>> listEntry : userData.getHistoryMap().entrySet()) {
            GoddessProto.GoddessEraHistoryListTemp.Builder builder = GoddessProto.GoddessEraHistoryListTemp.newBuilder();
            builder.setEraId(listEntry.getKey());
            for (GoddessEraHistory history : listEntry.getValue()) {
                GoddessProto.GoddessEraHistoryTemp.Builder historyBuilder = GoddessProto.GoddessEraHistoryTemp.newBuilder();
                historyBuilder.setType(history.getType());
                historyBuilder.setValue(history.getVal());
                historyBuilder.setTime(history.getTime());
                builder.addHistory(historyBuilder);
            }
            respMsg.addList(builder);
        }
        respMsg.setRet(0);
        player.sendPacket(Protocol.U_GODDESS_ERA_HISTORY_LIST, respMsg);
        return 0;
    }

    public int oneKeyUnLoad() {

        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        for (GoddessCell cell : userData.getCellList()) {
            cell.setStoneId(0);
        }

        for (Map.Entry<Integer, GoddessColorStone> stoneEntry : userData.getColorStoneMap().entrySet()) {
            stoneEntry.getValue().setCell(-1);
        }
        GoddessConfig config = GoddessMgr.getConfig();
        userData.setCellPoint(calCellAdditionPoint(userData, config));

        GoddessProto.GoddessOneKeyUnLoadCellRespMsg.Builder respMsg = GoddessProto.GoddessOneKeyUnLoadCellRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUserData(GoddessPb.buildUserData(userData));
        player.sendPacket(Protocol.U_GODDESS_ONE_KEY_CANCEL_INLAY, respMsg);
        return 0;
    }

    /**
     * 旋转石头
     */
    public int rotateStone(int stoneId) {

        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        GoddessColorStone stone = userData.getColorStoneMap().get(stoneId);
        if(stone == null){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        if(stone.getCell() > -1){
            //嵌入的不能旋转
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        stone.setFs(rotateRight(stone.getFs(), 5, 5));
        stone.setRe((stone.getRe() + 1) % 4);
        userData.setUpdateOption();

        GoddessProto.GoddessColorStoneRotateRespMsg.Builder builder = GoddessProto.GoddessColorStoneRotateRespMsg.newBuilder().setRet(0);
        builder.setColorStone(GoddessPb.buildColorStoneData(stone));
        player.sendPacket(Protocol.U_GODDESS_COLOR_STONE_ROTATE, builder);
        return 0;
    }

    /**
     * 补天
     */
    public int checkMissionPass() {
        if(userData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }
        GoddessConfig config = GoddessMgr.getConfig();
        GoddessEraInfo eraInfo = config.getGoddessEraInfo(userData.getEra());
        GoddessMissionInfo missionInfo = config.getGoddessMissionInfo(userData.getYearStatus().getMissionId());
        GoddessProto.GoddessCheckMissionPassRespMsg.Builder respMsg = GoddessProto.GoddessCheckMissionPassRespMsg.newBuilder();
        respMsg.setRet(0);

        //最后一重天不然补天
        if(userData.getYearStatus().getMissionId() == userData.getYearStatus().getMaxMissId()){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        long oldPoint = 0;
        if(passMission(config, missionInfo, eraInfo)){
            oldPoint = userData.getCellPoint();
            String reward = finishMission(config, missionInfo, eraInfo);
            respMsg.setMissionReward(reward);
        }else {
            return GameErrorCode.E_GODDESS_CHECK_PASS_FAIL;
        }
        respMsg.setOldPoint(oldPoint);
        userData.setUpdateOption();

        player.notifyListener(eGamePlayerEventType.GoddessMissionRank.getValue(), new ValueParamArgs(userData.getPassMissNum(), "" + userData.getCellPoint()));
        resetRankData();

        respMsg.setUserData(GoddessPb.buildUserData(userData));
        player.sendPacket(Protocol.U_GODDESS_CHECK_MISSION_PASS, respMsg);
        return 0;
    }

    //============ 辅助方法

    /**
     * 简单的旋转算法
     * @param formStr  1;0;0|1;0;0|1;1;1  或者 1  或者  1;1|0;1   或者  1| 1
     * @return
     * Array1（0，1，2）
     * Array2（0，1，2）
     * Array3（0，1，2）
     * 所有下标为0的按顺序写入新数组1,所有下标为1的按顺序写入新数组2……
     */
    private String rotateRight(String formStr, int row, int col){
        //GoddessMgr.getLogger().info("========= {}", formStr);
        List<List<Integer>> destList = new ArrayList<>();
        List<List<Integer>> srcList = new ArrayList<>();
        for (int i = 0; i < row; i++) {
            srcList.add(new ArrayList<>());
            destList.add(new ArrayList<>());
        }
        List<String> formStrList = StringUtils.stringToStringList(formStr, "\\|");
        for (int i = 0; i < formStrList.size(); i++) {
            srcList.set(i, StringUtils.stringToIntegerList(formStrList.get(i), ";"));
        }
        for (List<Integer> list : destList) {
            while(list.size() < col){
                list.add(0);
            }
        }
        for (List<Integer> list : srcList) {
            while(list.size() < col){
                list.add(0);
            }
        }
        for (int i = 0; i < srcList.size(); i++) {
            List<Integer> list = srcList.get(i);
            for (int k = 0; k < list.size(); k++) {
                destList.get(k).set(i, list.get(k));
            }
        }
        List<String> result = new ArrayList<>();
        for (int i = destList.size() - 1; i >= 0; i--) {
            result.add(StringUtils.listToString(destList.get(i), ";"));
        }
        //GoddessMgr.getLogger().info("============ {}", StringUtils.listToString(result, "|"));
        return StringUtils.listToString(result, "|");
    }

    //获取未镶嵌的五彩石数量
    private int getBagColorStoneNum(GoddessUserData userData){
        int num = 0;
        for (Map.Entry<Integer, GoddessColorStone> stoneEntry : userData.getColorStoneMap().entrySet()) {
            if(stoneEntry.getValue().getCell() < 0){
                num++;
            }
        }
        return num;
    }

    private List<Integer> randomStone(GoddessConfig config, GoddessEraInfo eraInfo, GoddessMissionInfo missionInfo, Random random) {
        List<Integer> result = new ArrayList<>();
        List<Integer> itemList = new ArrayList<>();
        List<Integer> weightList = new ArrayList<>();
        List<String> list = StringUtils.stringToStringList(missionInfo.getShapeWeight(), "\\|");
        for (String param : list) {
            List<Integer> vList = StringUtils.stringToIntegerList(param, ";");
            itemList.add(vList.get(0));
            weightList.add(vList.get(1));
        }
        int num = randomGetStoneNum(config, eraInfo, random);
        for (int i = 0; i < num; i++) {
            int idx = RandomHelper.getRandomIndexByWeight(weightList, random);
            result.add(itemList.get(idx));
        }
        return result;
    }

    private int randomGetStoneNum(GoddessConfig config, GoddessEraInfo eraInfo, Random random) {
        return randomRangeNum(eraInfo.getMakeNum(), random);
    }

    private int randomBasePoint(GoddessConfig config, Random random) {
        return randomRangeNum(config.getPointBaseRandom(), random);
    }

    private int randomRangeNum(String params, Random random) {
        List<Integer> itemList = new ArrayList<>();
        List<Integer> weightList = new ArrayList<>();
        List<String> list = StringUtils.stringToStringList(params, "\\|");
        for (String param : list) {
            List<Integer> vList = StringUtils.stringToIntegerList(param, ";");
            itemList.add(vList.get(0));
            weightList.add(vList.get(1));
        }
        int idx = RandomHelper.getRandomIndexByWeight(weightList, random);
        if(idx + 1 >= itemList.size()){
            idx = idx - 1;
        }
        int start = itemList.get(idx);
        int end = itemList.get(idx + 1);
        if(start == end){
            return start;
        }
        return start + random.nextInt(end - start);
    }

    //随机小人
    private List<Integer> randomPeople(GoddessUserData userData, GoddessConfig config, GoddessEraInfo eraInfo, Random random) {
        List<Integer> result = new ArrayList<>();
        for (GoddessPeopleInfo peopleInfo : config.getPeopleInfoList()) {
            if(userData.getPeoMap().containsKey(peopleInfo.getPeopleId())){
                //随机到的，不在出现
                continue;
            }
            List<String> rangeList = StringUtils.stringToStringList(peopleInfo.getWeight(), "\\|");
            for (int i = 0; i < rangeList.size(); i++) {
                List<Integer> list = StringUtils.stringToIntegerList(rangeList.get(i), ";");
                if(eraInfo.getEraId() >= list.get(0)){
                    if(random.nextInt(1000) < list.get(1)){
                        result.add(peopleInfo.getPeopleId());
                        break;
                    }
                }
            }
        }
        return result;
    }

    public int getLiangYiNum(GoddessUserData userData){
        int num = 0;
        for (GoddessYinYangStone stone : userData.getYangStoneList()) {
            if(stone.getPos() >= 0){
                continue;
            }
            num++;
        }
        for (GoddessYinYangStone stone : userData.getYinStoneList()) {
            if(stone.getPos() >= 0){
                continue;
            }
            num++;
        }
        return num;
    }

    private BigInteger calValueAddition(long val, int addition){
        return BigDecimal.valueOf(val).multiply(BigDecimal.valueOf(addition)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).toBigInteger();
    }

    //计算所有五彩石嵌入格子的点数
    private long calCellAdditionPoint(GoddessUserData userData, GoddessConfig config){
        long point = 0;
        //从背包五彩石计算
        for (Map.Entry<Integer, GoddessColorStone> stoneEntry : userData.getColorStoneMap().entrySet()) {
            GoddessColorStone colorStone = stoneEntry.getValue();
            point += calColorStonePoint(colorStone, userData, config);
        }
        return point;
    }

    //计算单个五彩石的点数
    private long calColorStonePoint(GoddessColorStone colorStone, GoddessUserData userData, GoddessConfig config){
        if(colorStone.getCell() < 0){
            return 0;
        }
        long point = 0;
        List<Integer> indexList = new ArrayList<>();
        for (GoddessCell cell : userData.getCellList()) {
            if(cell.getStoneId() == colorStone.getId()){
                indexList.add(cell.getPos());
            }
        }
        List<GoddessYinYangStone> yinYangStoneList = new ArrayList<>();
        for (int pos : indexList) {
            Position position = GoddessMgr.coordinate(pos, config);
            //阴仪石
            for (GoddessYinYangStone yinYangStone : userData.getYinStoneList()) {
                if (yinYangStone.getPos() > -1) {
                    if(position.getX() == yinYangStone.getPos()){
                        if(!yinYangStoneList.contains(yinYangStone)){
                            yinYangStoneList.add(yinYangStone);
                        }
                    }
                }
            }

            //阳仪石
            for (GoddessYinYangStone yinYangStone : userData.getYangStoneList()) {
                if (yinYangStone.getPos() > -1) {
                    if(position.getY() == yinYangStone.getPos()){
                        if(!yinYangStoneList.contains(yinYangStone)){
                            yinYangStoneList.add(yinYangStone);
                        }
                    }
                }
            }
        }

        //配置
        //GoddessRandomStoneInfo colorStoneInfo = config.getGoddessRandomStoneInfo(colorStone.getShapeId());
//        if(colorStoneInfo != null){
            //两仪石加成
            int addition = 0;
            for (GoddessYinYangStone yinYangStone : yinYangStoneList) {
                GoddessLiangYiStoneInfo liangYiStoneInfo = config.getGoddessLiangYiStoneInfo(yinYangStone.getLv());
                if(liangYiStoneInfo != null){
                    addition += liangYiStoneInfo.getAddEffect();
                }
            }
            if(addition == 0) {
                point += colorStone.getPt();
            }else {
                point += calValueAddition(colorStone.getPt(), addition + 1000).longValue();
            }
//        }
        return point;
    }

    //重天，获取解锁格子下标
    //0;0;0;0;0;0;0|0;0;0;0;0;0;0|0;0;1;1;1;0;0|0;0;1;1;1;0;0|0;0;1;1;1;0;0|0;0;0;0;0;0;0|0;0;0;0;0;0;0
    private List<Integer> getLandInfo(String landInfo, GoddessConfig config){
        List<Integer> result = new ArrayList<>();
        List<String> itemList = StringUtils.stringToStringList(landInfo, "\\|");
        for (int i = 0; i < itemList.size(); i++) {
            List<Integer> list = StringUtils.stringToIntegerList(itemList.get(i), ";");
            for (int k = 0; k < list.size(); k++) {
                if(list.get(k) == 1){
                    result.add(k + i * list.size());
                }
            }
        }
        return result;
    }

    //加纪元奖励
    private List<GoddessYinYangStone> addEraReward(GoddessUserData userData, GoddessConfig config, GoddessEraInfo nextEraInfo) {
        List<GoddessYinYangStone> list = new ArrayList<>();
        Property reward = PropertyHelper.parseStringToProperty(nextEraInfo.getEraReward());
        for (Map.Entry<Integer, BigInteger> entry : reward.getGoods().entrySet()) {
            int itemId = entry.getKey();
            long val = entry.getValue().longValue();
            if(itemId == eGoddessItems.SkyCell.getId()){
                for (int i = 0; i < val; i++) {
                    for (GoddessCell cell : userData.getCellList()) {
                        if(cell.getOpen() == 0){
                            cell.setOpen(1);
                            break;
                        }
                    }
                }
            }else if(itemId == eGoddessItems.YinYiStone.getId()){
                int addNum = config.getBagMaxNumLiangYi() - getLiangYiNum(userData);
                for (int i = 0; i < 1 && i < addNum; i++) {
                    list.add(addYinYiStone((int)val));
                }
            }else if(itemId == eGoddessItems.YangYiStone.getId()){
                int addNum = config.getBagMaxNumLiangYi() - getLiangYiNum(userData);
                for (int i = 0; i < 1 && i < addNum; i++) {
                    list.add(addYangYiStone((int)val));
                }
            }
        }
        return list;
    }

    //加五彩石到背包
    private Map<Integer, GoddessColorStone> addColorStoneToBag(GoddessUserData userData, int shapeId, long point, GoddessConfig config, int rotate) {
        GoddessRandomStoneInfo stoneInfo = config.getGoddessRandomStoneInfo(shapeId);
        Map<Integer, GoddessColorStone> resultMap = new HashMap<>();
        int maxId = userData.getYearStatus().getColorStoneMaxId() + 1;
        userData.getYearStatus().setColorStoneMaxId(maxId);
        GoddessColorStone stone = new GoddessColorStone(maxId);
        stone.setPt(point);
        stone.setSd(shapeId);
        stone.setRe(rotate);
        stone.setFs(stoneInfo.getShape());
        if(rotate > 0){
            int temp = rotate;
            while (temp > 0){
                stone.setFs(rotateRight(stone.getFs(), 5, 5));
                temp--;
            }
        }
        resultMap.put(stone.getId(), stone);
        userData.getColorStoneMap().putAll(resultMap);
        return resultMap;
    }

    //新增阳仪石到背包
    private GoddessYinYangStone addYangYiStone(int lv) {
        int maxId = 0;
        for (GoddessYinYangStone yinYangStone : userData.getYangStoneList()) {
            if(yinYangStone.getId() > maxId){
                maxId = yinYangStone.getId();
            }
        }
        GoddessYinYangStone stone = new GoddessYinYangStone(maxId + 1);
        stone.setLv(lv);
        stone.setType(1);
        userData.getYangStoneList().add(stone);
        return stone;
    }

    //新增阴仪石到背包
    private GoddessYinYangStone addYinYiStone(int lv) {
        int maxId = 0;
        for (GoddessYinYangStone yangYangStone : userData.getYinStoneList()) {
            if(yangYangStone.getId() > maxId){
                maxId = yangYangStone.getId();
            }
        }
        GoddessYinYangStone stone = new GoddessYinYangStone(maxId + 1);
        stone.setLv(lv);
        stone.setType(0);
        userData.getYinStoneList().add(stone);
        return stone;
    }

    //获取两仪石
    private GoddessYinYangStone getGoddessYinYangStone(GoddessUserData userData, int id, int type) {
        GoddessYinYangStone stone = null;
        if(type == 0){
            for (GoddessYinYangStone temp : userData.getYinStoneList()) {
                if(temp.getId() == id){
                    stone = temp;
                }
            }
        }else if(type == 1){
            for (GoddessYinYangStone temp : userData.getYangStoneList()) {
                if(temp.getId() == id){
                    stone = temp;
                }
            }
        }
        return stone;
    }

    //移除两仪石
    private boolean removeGoddessYinYangStone(GoddessUserData userData, int id, int type){
        Iterator<GoddessYinYangStone> iterator = null;
        if(type == 0){
            iterator = userData.getYinStoneList().iterator();
        }else if(type == 1){
            iterator = userData.getYinStoneList().iterator();
        }
        if(iterator != null){
            while (iterator.hasNext()){
                GoddessYinYangStone stone = iterator.next();
                if(stone.getId() == id){
                    iterator.remove();
                    return true;
                }
            }
        }
        return false;
    }

    public GoddessUserData getUserData() {
        return userData;
    }
}
